import express, { Express, Request, Response, NextFunction } from 'express';
import cors from 'cors';
import helmet from 'helmet';
import morgan from 'morgan';
import compression from 'compression';
import rateLimit from 'express-rate-limit';
import { Server } from 'socket.io';
import { createServer } from 'http';

import config from '@config/index';
import logger from '@utils/logger';
import { setupSwagger } from '@config/swagger';

// 中间件
import errorHandler from '@middleware/errorHandler';
import notFound from '@middleware/notFound';
import {
  requestIdMiddleware,
  requestLoggingMiddleware,
  errorLoggingMiddleware
} from '@middleware/requestId';

// 路由 (暂时注释，后续实现)
// import authRoutes from '@routes/auth';
// import alertRoutes from '@routes/alerts';
// import ticketRoutes from '@routes/tickets';
// import knowledgeRoutes from '@routes/knowledge';
// import analyticsRoutes from '@routes/analytics';
// import userRoutes from '@routes/users';
// import systemRoutes from '@routes/system';

class App {
  public app: Express;
  public server: any;
  public io: Server;

  constructor() {
    this.app = express();
    this.server = createServer(this.app);
    this.io = new Server(this.server, {
      cors: {
        origin: config.env.CORS_ORIGIN,
        methods: ['GET', 'POST'],
      },
    });

    this.initializeMiddleware();
    this.initializeSwagger();
    this.initializeRoutes();
    this.initializeErrorHandling();
    this.initializeWebSocket();
  }

  /**
   * 初始化 Swagger API 文档
   */
  private initializeSwagger(): void {
    setupSwagger(this.app);
    logger.info('Swagger API documentation initialized at /api/docs');
  }

  /**
   * 初始化中间件
   */
  private initializeMiddleware(): void {
    // Request ID middleware - must be first for proper tracing
    this.app.use(requestIdMiddleware);

    // Request logging middleware - early in chain for comprehensive logging
    this.app.use(requestLoggingMiddleware);

    // 安全中间件
    this.app.use(helmet({
      contentSecurityPolicy: {
        directives: {
          defaultSrc: ["'self'"],
          styleSrc: ["'self'", "'unsafe-inline'"],
          scriptSrc: ["'self'"],
          imgSrc: ["'self'", "data:", "https:"],
        },
      },
    }));

    // CORS 配置 - 支持多个源(开发环境)
    const allowedOrigins = config.env.CORS_ORIGIN.split(',').map(origin => origin.trim());
    this.app.use(cors({
      origin: (origin, callback) => {
        // 允许没有 origin 的请求(如 Postman, curl)
        if (!origin) return callback(null, true);

        if (allowedOrigins.includes(origin)) {
          callback(null, true);
        } else {
          callback(new Error('Not allowed by CORS'));
        }
      },
      methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
      allowedHeaders: ['Content-Type', 'Authorization'],
      credentials: true,
    }));

    // 压缩响应
    this.app.use(compression());

    // 请求体解析
    this.app.use(express.json({ limit: '10mb' }));
    this.app.use(express.urlencoded({ extended: true, limit: '10mb' }));

    // 请求日志
    if (config.isDevelopment) {
      this.app.use(morgan('dev'));
    } else {
      this.app.use(morgan('combined', {
        stream: {
          write: (message: string) => {
            logger.info(message.trim());
          },
        },
      }));
    }

    // 速率限制
    const limiter = rateLimit({
      windowMs: config.env.RATE_LIMIT_WINDOW * 60 * 1000, // 转换为毫秒
      max: config.env.RATE_LIMIT_MAX,
      message: {
        error: 'Too many requests, please try again later.',
      },
      standardHeaders: true,
      legacyHeaders: false,
    });
    this.app.use(limiter);

    // 信任代理（如果在代理后面）
    if (config.isProduction) {
      this.app.set('trust proxy', 1);
    }
  }

  /**
   * 初始化路由
   */
  private initializeRoutes(): void {
    /**
     * @swagger
     * /health:
     *   get:
     *     summary: Comprehensive health check
     *     description: Returns detailed health status including database, Redis, and memory checks
     *     tags: [System]
     *     responses:
     *       200:
     *         description: Service is healthy or degraded
     *       503:
     *         description: Service is unhealthy
     */
    // Health check endpoint - comprehensive health status
    this.app.get('/health', async (req: Request, res: Response) => {
      try {
        const { performHealthCheck } = await import('@utils/healthCheck');
        const health = await performHealthCheck();

        const statusCode = health.status === 'healthy' ? 200 : health.status === 'degraded' ? 200 : 503;

        res.status(statusCode).json({
          success: health.status !== 'unhealthy',
          ...health,
        });
      } catch (error) {
        logger.error('Health check failed:', error as Error);
        res.status(503).json({
          success: false,
          status: 'unhealthy',
          message: 'Health check failed',
          error: (error as Error).message,
        });
      }
    });

    /**
     * @swagger
     * /ready:
     *   get:
     *     summary: Readiness probe
     *     description: Kubernetes readiness check - returns 200 only if ready to accept traffic
     *     tags: [System]
     *     responses:
     *       200:
     *         description: Service is ready
     *       503:
     *         description: Service is not ready
     */
    // Readiness check endpoint - for Kubernetes readiness probe
    this.app.get('/ready', async (req: Request, res: Response) => {
      try {
        const { performReadinessCheck } = await import('@utils/healthCheck');
        const readiness = await performReadinessCheck();

        const statusCode = readiness.ready ? 200 : 503;

        res.status(statusCode).json({
          success: readiness.ready,
          ...readiness,
        });
      } catch (error) {
        logger.error('Readiness check failed:', error as Error);
        res.status(503).json({
          success: false,
          ready: false,
          message: 'Readiness check failed',
          error: (error as Error).message,
        });
      }
    });

    /**
     * @swagger
     * /live:
     *   get:
     *     summary: Liveness probe
     *     description: Kubernetes liveness check - simple ping to verify process is alive
     *     tags: [System]
     *     responses:
     *       200:
     *         description: Service is alive
     */
    // Liveness check endpoint - simple ping for Kubernetes liveness probe
    this.app.get('/live', (req: Request, res: Response) => {
      res.status(200).json({
        success: true,
        alive: true,
        timestamp: new Date().toISOString(),
      });
    });

    /**
     * @swagger
     * /version:
     *   get:
     *     summary: Get service version
     *     description: Returns version, environment, and runtime information
     *     tags: [System]
     *     responses:
     *       200:
     *         description: Version information retrieved successfully
     */
    // Version endpoint
    this.app.get('/version', (req: Request, res: Response) => {
      res.status(200).json({
        success: true,
        version: process.env.npm_package_version || '1.0.0',
        name: 'DevOps SmartBot API',
        environment: config.env.NODE_ENV,
        nodeVersion: process.version,
        uptime: Math.floor(process.uptime()),
      });
    });

    // API 根路径
    this.app.get(config.env.API_PREFIX, (req: Request, res: Response) => {
      res.status(200).json({
        success: true,
        message: 'DevOps SmartBot API',
        version: process.env.npm_package_version || '1.0.0',
        environment: config.env.NODE_ENV,
        documentation: `${config.env.API_PREFIX}/docs`,
      });
    });

    // API 路由
    const authRoutes = require('./routes/auth.routes').default;
    const alertRoutes = require('./routes/alert.routes').default;
    const prometheusRoutes = require('./routes/prometheus.routes').default;
    const dataSourceRoutes = require('./routes/datasource.routes').default;
    const ticketRoutes = require('./routes/ticket.routes').default;
    const crawlerRoutes = require('./routes/crawler.routes').default;
    const systemRoutes = require('./routes/system.routes').default;
    const analyticsRoutes = require('./routes/analytics.routes').default;
    const dashboardRoutes = require('./routes/dashboard.routes').default;
    const knowledgeRoutes = require('./routes/knowledge.routes').default;
    const settingsRoutes = require('./routes/settings.routes').default;
    // const organizationRoutes = require('./routes/organization.routes').default; // TODO: Fix RBAC TypeScript errors

    this.app.use(`${config.env.API_PREFIX}/auth`, authRoutes);
    this.app.use(`${config.env.API_PREFIX}/alerts`, alertRoutes);
    this.app.use(`${config.env.API_PREFIX}/prometheus`, prometheusRoutes);
    this.app.use(`${config.env.API_PREFIX}/datasources`, dataSourceRoutes);
    this.app.use(`${config.env.API_PREFIX}/tickets`, ticketRoutes);
    this.app.use(`${config.env.API_PREFIX}/crawlers`, crawlerRoutes);
    this.app.use(`${config.env.API_PREFIX}/system`, systemRoutes);
    this.app.use(`${config.env.API_PREFIX}/analytics`, analyticsRoutes);
    this.app.use(`${config.env.API_PREFIX}/dashboard`, dashboardRoutes);
    this.app.use(`${config.env.API_PREFIX}/knowledge`, knowledgeRoutes);
    this.app.use(`${config.env.API_PREFIX}/settings`, settingsRoutes);
    // this.app.use(`${config.env.API_PREFIX}/organizations`, organizationRoutes); // TODO: Fix RBAC TypeScript errors
  }

  /**
   * 初始化错误处理
   */
  private initializeErrorHandling(): void {
    // 404 处理
    this.app.use(notFound);

    // Error logging middleware - logs errors with request context
    this.app.use(errorLoggingMiddleware);

    // 全局错误处理
    this.app.use(errorHandler);

    // 未捕获的异常处理
    process.on('uncaughtException', (error: Error) => {
      logger.error('Uncaught Exception:', error);
      process.exit(1);
    });

    // 未处理的 Promise 拒绝
    process.on('unhandledRejection', (reason: any) => {
      logger.error('Unhandled Rejection:', reason);
      process.exit(1);
    });

    // 优雅关闭
    process.on('SIGTERM', this.gracefulShutdown.bind(this));
    process.on('SIGINT', this.gracefulShutdown.bind(this));
  }

  /**
   * 初始化 WebSocket
   */
  private initializeWebSocket(): void {
    this.io.on('connection', (socket) => {
      logger.info(`WebSocket client connected: ${socket.id}`);

      // User authentication (to be implemented)
      socket.on('authenticate', (token: string) => {
        // TODO: Implement JWT token verification
        logger.info(`Client ${socket.id} authenticated`);
      });

      // 加入告警房间
      socket.on('join-alerts', () => {
        socket.join('alerts');
        logger.info(`Client ${socket.id} joined alerts room`);
      });

      // 加入工单房间
      socket.on('join-tickets', () => {
        socket.join('tickets');
        logger.info(`Client ${socket.id} joined tickets room`);
      });

      // 断开连接
      socket.on('disconnect', () => {
        logger.info(`WebSocket client disconnected: ${socket.id}`);
      });
    });

    logger.info('WebSocket server initialized');
  }

  /**
   * 广播告警事件
   */
  public broadcastAlert(event: string, data: any): void {
    this.io.to('alerts').emit(event, data);
  }

  /**
   * 广播工单事件
   */
  public broadcastTicket(event: string, data: any): void {
    this.io.to('tickets').emit(event, data);
  }

  /**
   * 广播系统通知
   */
  public broadcastNotification(event: string, data: any): void {
    this.io.emit(event, data);
  }

  /**
   * 优雅关闭
   */
  private async gracefulShutdown(signal: string): Promise<void> {
    logger.info(`Received ${signal}, starting graceful shutdown...`);

    // 停止接受新连接
    this.server.close(() => {
      logger.info('HTTP server closed');
    });

    // 关闭 WebSocket 连接
    this.io.close(() => {
      logger.info('WebSocket server closed');
    });

    // 给进程一些时间完成正在进行的请求
    setTimeout(() => {
      logger.info('Graceful shutdown completed');
      process.exit(0);
    }, 10000);
  }

  /**
   * 启动服务器
   */
  public listen(): void {
    const port = config.env.PORT;
    
    this.server.listen(port, () => {
      logger.info(`Server running on port ${port} in ${config.env.NODE_ENV} mode`);
      logger.info(`API available at http://localhost:${port}${config.env.API_PREFIX}`);
      logger.info(`Health check at http://localhost:${port}/health`);
    });
  }
}

export default App;